嗨大家好,我是Sean!
寫到今天,整個鐵人賽的系列也到了一半的地方了,
大部分關於Django的架構以及Django rest framework大致上的概念以及簡單操作,都放在那裏了!去尋找吧!(其實就在底下的連結)
好的,總而言之,比較偏理論示範的部分已經告一個段落了!
接下來的部分,可能會偏向針對實戰常見的小專案以及實務中我所遇到並解決的後端問題為主。
有些遇見的實務問題,我想應該也會對很多新接觸Django的朋友很有幫助。
相信對學習coding的大家來說,遇到問題並解決的這個部分,也是coding的一大樂趣嗎(?
那麼,就讓我們進入第一個實戰篇的部分,大部分人在學習、熟悉框架的時候,都會學到的使用者註冊。
網頁與使用者幾乎是分不開的兩個部分,比起以往大多是匿名使用的網站,近期很熱門的會員訂閱制,都讓使用者的部分更加重要了。
在我們的Day06的關聯資料篇,曾經有提到過關於使用者的部分,其中一個原因是由於常用的一對一關係(OneToOneField),就是使用在原生auth.User身上。
這裡我們就來實作這個方法,讓大家看看運用原生table而做成的UserProfile會有甚麼效果。
首先,我們先來Django的official document看看,它裡面有包含哪些內容。
https://docs.djangoproject.com/en/4.1/ref/contrib/auth/#django.contrib.auth.models.User
光是基本的原生model就已經有:
在我們建立model之前,先參考有哪些欄位是可以直接使用的,避免重複了相同的欄位。
以上的這些欄位內容,其實在我們進入admin的管理者頁面,也可以看的到。
在底下也有原生的Group model可以做使用!
接下來我們來擴充User的model,用UserProfile這個model來做一對一的關聯。
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=10, blank=True, null=True)
organization = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.user.username
進行了migration以後,我們就可以來寫serializer, view的部分了。
首先我們必須寫serializer,依靠他的驗證以及一同建立User以及UserProfile的部分。
from django.contrib.auth.models import User
from .models import UserProfile
from rest_framework.validators import UniqueValidator
from django.contrib.auth.password_validation import validate_password
class RegisterSerializer(serializers.ModelSerializer):
username = serializers.CharField(
required=True,
validators=[UniqueValidator(queryset=User.objects.all())],
)
password = serializers.CharField(write_only=True, required=True, validators=[validate_password],
style={'input_type': 'password'})
password2 = serializers.CharField(write_only=True, required=True, style={'input_type': 'password'})
email = serializers.EmailField(write_only=True, required=True)
phone = serializers.CharField(min_length=8, max_length=10, write_only=True)
organization = serializers.CharField(max_length=100)
class Meta:
model = User
fields = ('username', 'email', 'password', 'password2', 'phone', 'organization')
def validate(self, attrs):
if attrs['password'] != attrs['password2']:
raise serializers.ValidationError({"password": "Password fields didn't match."})
return attrs
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username'],
email=validated_data['email'],
password=validated_data['password'],
)
userprofile = UserProfile.objects.create(
user=user,
phone=validated_data['phone'],
organization=validated_data['organization'],
)
user.set_password(validated_data['password'])
user.save()
return user
讓我們來分析一下,以上做了哪些事:
2.model的部分主要還是使用User為主,UserProfile是擴充包,在fields裡,仍必須把我們UserProfile裡的欄位寫進去。
3.我們使用ORM的方法來create model instance,一方面重新定義create,另一方面我們也同時create UserProfile的 instance,並對應我們創建的User instance。
4.最後,儲存密碼並且return user
from rest_framework import generics
from .serializers import RegisterSerializer
class RegisterAPIView(generics.GenericAPIView):
serializer_class = RegisterSerializer
def post(self, request):
serializer = self.serializer_class(data = request.data)
if serializer.is_valid():
serializer.save()
return Response({
'message': 'Account has been created successfully'
},
status=status.HTTP_201_CREATED
)
return Response({
'message': 'The input content is invalid'
},
status=status.HTTP_400_BAD_REQUEST
)
view的部分,我們用GenericAPIView來做,他是一個可以自定義的api view。
寫完必要的serializer_class以後,我們定義使用post method的功能:
讓輸入的值成為serializer可以使用data=request.data,
接著,在save之前,我們得先用is_valid()的功能來驗證serializer,
最後在Response的地方回傳訊息以及status,一支用來註冊的後端api就大功告成了!
完成的畫面會像下面的畫面這樣!
那麼,今天的文章就到此結束!感謝大家的收看!
我是Sean,你各位海上的人,我們明天見!